import { Injectable } from '@nestjs/common';
import { ResultData } from 'src/common/utils/result';
import { CreateDeptDto, UpdateDeptDto, ListDeptDto } from './dto/index';
import { ListToTree } from 'src/common/utils/index';
import { CacheEnum, DataScopeEnum } from 'src/common/enum/index';
import { Cacheable, CacheEvict } from 'src/common/decorators/redis.decorator';
import { PrismaService } from '@/module/common/prisma/prisma.service';
import { pickEquals, pickLike } from '@/common/utils/prisma';

@Injectable()
export class DeptService {
    constructor(
        private readonly prisma: PrismaService
    ) { }

    @CacheEvict(CacheEnum.SYS_DEPT_KEY, '*')
    async create(createDeptDto: CreateDeptDto) {
        if (createDeptDto.parentId) {
            const parent = await this.prisma.dept.findUnique({
                where: {
                    deptId: createDeptDto.parentId,
                    delFlag: '0',
                }
            })
            if (!parent) {
                return ResultData.fail(500, '父级部门不存在');
            }
            const ancestors = parent.ancestors ? `${parent.ancestors},${createDeptDto.parentId}` : `${createDeptDto.parentId}`;
            Object.assign(createDeptDto, { ancestors: ancestors });
        }
        await this.prisma.dept.create({
            data: createDeptDto
        })
        return ResultData.ok();
    }

    async findAll(query: ListDeptDto) {
        const res = await this.prisma.dept.findMany({
            where: {
                delFlag: '0',
                ...pickLike(query, ['deptName']),
                ...pickEquals(query, ['status']),
            }
        })
        return ResultData.ok(res);
    }

    @Cacheable(CacheEnum.SYS_DEPT_KEY, 'findOne:{deptId}')
    async findOne(deptId: number) {
        const data = await this.prisma.dept.findUnique({
            where: {
                deptId: deptId,
                delFlag: '0',
            }
        })
        return ResultData.ok(data);
    }

    /**
     * 根据数据权限范围和部门ID查询部门ID列表。
     * @param deptId 部门ID，表示需要查询的部门。
     * @param dataScope 数据权限范围，决定查询的部门范围。
     * @returns 返回一个部门ID数组，根据数据权限范围决定返回的部门ID集合。
     */
    @Cacheable(CacheEnum.SYS_DEPT_KEY, 'findDeptIdsByDataScope:{deptId}-{dataScope}')
    async findDeptIdsByDataScope(deptId: number, dataScope: DataScopeEnum) {
        let where: any = {
            delFlag: '0',
        };
        try {

            // 根据不同的数据权限范围添加不同的查询条件
            if (dataScope === DataScopeEnum.DATA_SCOPE_DEPT) {
                // 如果是本部门数据权限，则只查询指定部门
                this.addQueryForDeptDataScope(where, deptId);
            } else if (dataScope === DataScopeEnum.DATA_SCOPE_DEPT_AND_CHILD) {
                // 如果是本部门及子部门数据权限，则查询指定部门及其所有子部门
                this.addQueryForDeptAndChildDataScope(where, deptId);
            } else if (dataScope === DataScopeEnum.DATA_SCOPE_SELF) {
                // 如果是仅本人数据权限，则不查询任何部门，直接返回空数组
                return [];
            }
            // 执行查询并获取结果
            const list = await this.prisma.dept.findMany({ where })
            // 将查询结果映射为部门ID数组后返回
            return list.map((item) => item.deptId);
        } catch (error) {
            console.error('Failed to query department IDs:', error);
            throw new Error('Querying department IDs failed');
        }
    }

    /**
     * 添加查询条件以适应本部门数据权限范围。
     * @param queryBuilder 查询构建器实例
     * @param deptId 部门ID
     */
    private addQueryForDeptDataScope(where: any, deptId: number) {
        where.deptId = deptId;
    }

    /**
     * 添加查询条件以适应本部门及子部门数据权限范围。
     * @param queryBuilder 查询构建器实例
     * @param deptId 部门ID
     */
    private addQueryForDeptAndChildDataScope(where: any, deptId: number) {
        // 使用参数化查询以防止SQL注入
        where.OR = [
            { ancestors: { contains: deptId.toString() } }, // 使用 contains 实现 LIKE '%deptId%'
            { deptId: deptId }, // 直接匹配 deptId
        ]
    }

    @Cacheable(CacheEnum.SYS_DEPT_KEY, 'findListExclude')
    async findListExclude(id: number) {
        //TODO 需排出ancestors 中不出现id的数据
        const data = await this.prisma.dept.findMany({
            where: {
                delFlag: '0', // 过滤 delFlag 为 '0' 的记录
                NOT: {
                    ancestors: { contains: id.toString() }, // 排除 ancestors 中包含 id 的记录
                },
            },
        });
        return ResultData.ok(data);
    }

    @CacheEvict(CacheEnum.SYS_DEPT_KEY, '*')
    async update(updateDeptDto: UpdateDeptDto) {
        if (updateDeptDto.parentId && updateDeptDto.parentId !== 0) {
            const parent = await this.prisma.dept.findUnique({
                where: {
                    deptId: updateDeptDto.parentId,
                    delFlag: '0',
                },
                select: {
                    ancestors: true,
                }
            })
            if (!parent) {
                return ResultData.fail(500, '父级部门不存在');
            }
            const ancestors = parent.ancestors ? `${parent.ancestors},${updateDeptDto.parentId}` : `${updateDeptDto.parentId}`;
            Object.assign(updateDeptDto, { ancestors: ancestors });
        }
        await this.prisma.dept.update({
            where: {
                deptId: updateDeptDto.deptId,
            },
            data: updateDeptDto
        })
        return ResultData.ok();
    }

    @CacheEvict(CacheEnum.SYS_DEPT_KEY, '*')
    async remove(deptId: number) {
        const data = await this.prisma.dept.update({
            where: {
                deptId
            },
            data: {
                delFlag: '1'
            }
        })
        return ResultData.ok(data);
    }

    /**
     * 部门树
     * @returns
     */
    @Cacheable(CacheEnum.SYS_DEPT_KEY, 'deptTree')
    async deptTree() {
        const res = await this.prisma.dept.findMany({
            where: {
                delFlag: '0',
            }
        })
        const tree = ListToTree(
            res,
            (m) => m.deptId,
            (m) => m.deptName,
        );
        return tree;
    }
}
